﻿#pragma once
namespace LK
{
	namespace Reflection
	{
		struct PFunctionNode :ptr<LibraryNode>
		{
			//基类通用方法
			PMETHODS(PFunctionNode, FunctionNode);
			/**
			@brief 添加函数重载,并按照传参调用的需要排序，domain用以指定作用域节点，默认为当前节点所在作用域
			@return 如果添加成功，则返回true，如果有重复，或者作用域不一致，则返回false*/
			bool AddFunction(Functional::PFunObjs fun)const;
			bool AddFunction(Functional::PFunObjs fun, PDomainNode domain)const;
			/**
			@brief 添加函数重载,并按照转换函数的需要排序，如果添加成功，则返回true，如果有重复，则返回false*/
			bool AddOperatorFunction(Functional::PFunObjs fun)const;
			/**
			@brief 动态传参并调用方法
			@note 该方法在找不到合适的重载时会抛出FunctionOverloadNotFoundException*/
			ptr<Object> DynamicCall(ptr<Object> const& obj, ptr<Collection::IArray<ptr<Object>>>args)const;
			/**
			@brief 动态传入参数类型以获取调用的重载版本
			@param [传入，可省]参数isExplicit用以指示是否精确匹配，默认为false
			@note 该方法在找不到合适的重载时返回NULL*/
			Functional::PFunObjs GetFunction(ptr<Collection::IArray<ptr<Type>>>args, bool isExplicit = false)const;
			/**
			@brief 快速动态传参并调用方法
			@note 该方法在找不到合适的重载时会抛出PInvalidArgumentException*/
			//template<class ReturnType, class ...Arguments>ReturnType FastCall(void const* objectPtr, Arguments...t)const;
		};
		struct FunctionNode :LibraryNode
		{
			//基类通用方法
			BMETHODS(PFunctionNode, FunctionNode)
				//构造函数
				FunctionNode(ptr<String> const& name, weakptr<TypeLibrary> const& library = Convert<weakptr<TypeLibrary> const&, ptr<Object>>::RefFrom(ptr<Object>()), PDomainNode const& baseNode = ptr<LibraryNode>::EmptyNode);
			//关联的函数
			ptr<Collection::IArray<Functional::PFunObjs>> Methods;
			//该域内是否有函数
			bool InDomain;
			//添加函数,并按照传参调用的需要排序，如果添加成功，则返回true，如果有重复，则返回false，domain指定作用域，默认为空(表示当前节点所在作用域)
			bool AddFunction(Functional::PFunObjs fun);
			bool AddFunction(Functional::PFunObjs fun, PDomainNode domain);
			//添加函数,并按照转换函数的需要排序，如果添加成功，则返回true，如果有重复，则返回false
			bool AddOperatorFunction(Functional::PFunObjs fun);
			/**
			@brief 动态传入参数类型以获取调用的重载版本
			@param [传入，可省]参数isExplicit用以指示是否精确匹配，默认为false
			@note 该方法在找不到合适的重载时返回NULL*/
			Functional::PFunObjs GetFunction(ptr<Collection::IArray<ptr<Type>>>args, bool isExplicit = false)const;
			//函数比较方法，用以进行调用方式排序
			static index_t FunctionCompare(Functional::PFunObjs const&, Functional::PFunObjs const&);
			//函数比较方法，用以进行调用方式排序
			static index_t FunctionTypeCompare(Functional::PFunObjs const&, ptr<Collection::IArray<ptr<Type>>> const&);
			//转换函数比较方法，用以进行转换方式排序
			static index_t OperatorFunctionCompare(Functional::PFunObjs const&, Functional::PFunObjs const&);
			//转换函数比较方法，用以进行构造函数模糊查询
			static index_t ConstructCompare(Functional::PFunObjs const&, ptr<Collection::IArray<ptr<Type>>> const&);
			//转换函数比较方法，用以进行转换函数模糊查询
			static index_t OperatorCompare(Functional::PFunObjs const&, ptr<Type> const&);
		};
		/**
		@brief 快速动态传参并调用方法
		@note 该方法在找不到合适的重载时会抛出PInvalidArgumentException*/
		template<class RArgsPack>struct FunctionNodeFastCall;
#ifdef SUPPORT_VARIADIC_TEMPLATES
		template<class ReturnType, class ...ArgumentTypes> struct FunctionNodeFastCall<ReturnType(ArgumentTypes...) >
		{
			static ReturnType FastCall(PFunctionNode node, const void*objectPtr, ArgumentTypes...t)
			{
				for (index_t i = 0; i < (node.Check()->Methods==null ? 0 : node.GetPtr()->Methods->size()); ++i)
				{
					typedef Functional::PFunObj<VarArgsPack<ReturnType,ArgumentTypes...> > Fun;
					Fun x = cast<Fun>(node.GetPtr()->Methods[i]);
#if 0
					; if (GetGlobleLibrary().GetTypeNodeByInfo(node.GetPtr()->Methods[i].GetType()).IsDerivedFrom(
						GetGlobleLibrary().GetTypeNodeByInfo(ptr<Type>::template Make<Fun>())))x = (Fun&)node.GetPtr()->Methods[i];
#endif
					if (!x==null)return x.ThisCall((void*)objectPtr, t...);
				}
				return RThrow<ReturnType, ptr<FunctionOverloadNotFoundException> >();
			}
		};
#else
#define TMPCT(x) ,class T##x
#define TMPT(x) ,T##x
#define TMPTt(x) ,T##x t##x
#define TMPt(x) ,t##x
#define TMPF(x)\
		template<class ReturnType MF3_RepeatAsc(TMPCT,2,x)>struct FunctionNodeFastCall<ReturnType(MF4_RepeatAsc_(T,,2,x)) >{\
			static ReturnType FastCall(PFunctionNode node, const void*objectPtr MF3_RepeatAsc(TMPTt,2,x)){\
				for (index_t i = 0; i < (node.Check()->Methods==null ? 0 : node.GetPtr()->Methods.GetLength()); ++i){\
					typedef Functional::PFunObj<VarArgsPack<ReturnType,MF4_RepeatAsc_(T,,2,x)> > Fun;\
					Fun xx = node.GetPtr()->Methods[i].CastTo<Fun>();\
					if(!xx==null)return xx.ThisCall((void*)objectPtr MF3_RepeatAsc(TMPt,2,x));}\
				return RThrow<ReturnType,ptr<FunctionOverloadNotFoundException> >();}\
		};
		MF2_Repeatb(TMPF, _MRP_CNTM2)
#undef TMPF
#undef TMPCT
#undef TMPT
#undef TMPTt
#undef TMPt


#endif
	}
}
